﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using _2QWebProxy.App_Code;

namespace _2QWebProxy
{
    public class ProxyClient
    {
        public Thread ReceiveThread;
        public Socket client;
        public CClient browserClient;


        public ProxyClient(string ip, int port, CClient browserClient)
        {
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            this.browserClient = browserClient;
            do
            {
                try
                {
                    client.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
                }
                catch (Exception ex) { }
            } while (!client.Connected);
            this.ReceiveThread = new Thread(new ThreadStart(RedirectPackets));
            this.ReceiveThread.Start();

        }

        private void RedirectPackets()
        {

            try
            {
                byte[] buffer;
                bool flag = false;
                while (client.Connected)
                {
                    buffer = new byte[65535];
                    int recv = client.Receive(buffer);
                    Array.Resize(ref buffer, recv);
                    // Apply rule
                    bool rule = true;
                    if (recv == 0)
                    {
                        this.ReceiveThread.Abort();
                        return;
                    }
                    if (Properties.Settings.Default.isRule)
                    {
                        string contentType = Utils.FilterHeader(Encoding.GetEncoding("UTF-8").GetString(buffer), "Content-Type");
                        if (flag && contentType != "")
                        {
                            flag = false;
                        }
                        rule = (!flag && Utils.CheckRules(GlobalVariables.host, GlobalVariables.ipAddress, contentType, GlobalVariables.ruleType));
                        if (!rule)
                        {
                            //if (contentType != "")
                            //{
                            if (flag)
                            {
                                string str = "\r\n";
                                buffer = Encoding.ASCII.GetBytes(str);
                                browserClient.SendToBrowser(buffer);
                                flag = true;
                            }
                            else
                            {
                                string str = Encoding.GetEncoding("UTF-8").GetString(buffer);
                                str = str.Substring(0, str.IndexOf("\r\n\r\n")) + "\r\n";
                                buffer = Encoding.GetEncoding("UTF-8").GetBytes(str);
                                browserClient.SendToBrowser(buffer);
                                flag = true;
                                //this.ReceiveThread.Abort();
                            }
                            continue;
                            //}
                            //else
                            //{
                            //    
                            //}
                        }

                    }
                    //if (Properties.Settings.Default.isCache)
                    //{
                    //    List<Tuple<String, String>> listRequest;
                    //    Utils.ReadRequestHeaders(browserClient.RequestHeader, out listRequest);
                    //    List<Tuple<String, String>> listResponse;
                    //    Utils.ReadReponseHeaders(Encoding.GetEncoding("UTF-8").GetString(buffer), out listResponse);
                    //    CacheRecord cache = Cache.SaveCache(listRequest, listResponse);
                    //    string strStatus = Utils.BuildResponseStatus(Int32.Parse(cache.StatusCode), cache.StatusDescription);
                    //    string strHeader = Utils.BuildResponseHeaders(cache.Headers);
                    //    if (cache.ResponseBytes != null)
                    //    {
                    //        browserClient.SendToBrowser(cache.ResponseBytes);
                    //    }
                    //    else
                    //    {
                    //        browserClient.SendToBrowser(buffer);
                    //    }
                    //}
                    //Send request to browser
                    if (rule)
                    {
                        browserClient.SendToBrowser(buffer);

                    }
                    else
                    {
                        flag = true;
                    }
                }
            }
            catch (Exception ex)
            {

            }

        }
        public string GetHeader(Socket socket, out byte[] arrByte)
        {
            string header = "";
            int i = 0;
            arrByte = new byte[65535];
            while (true)
            {
                byte[] bytes = new byte[1];
                int bytesRec = socket.Receive(bytes);
                header += System.Text.Encoding.ASCII.GetString(bytes, 0, bytesRec);
                arrByte[i] = bytes[0];
                i++;
                if (header.IndexOf("\r\n\r\n") > -1 || header.IndexOf("\n\n") > -1)
                {
                    break;
                }
            }
            Array.Resize(ref arrByte, i);
            return header;
        }

        public void SendToServer(byte[] packet)
        {
            client.Send(packet);
        }
    }
}
